﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using Ipmce.RemoteVoting.Common.Entities;
using Ipmce.RemoteVoting.Frontend.VotingApplication.Properties;
using Ipmce.RemoteVoting.Frontend.VotingApplication.Utils;
using Ipmce.RemoteVoting.Frontend.VotingLibrary;

namespace Ipmce.RemoteVoting.Frontend.VotingApplication.ViewModel
{
	class MainWindowViewModel : ViewModelBase
	{
		private enum AuthorizationMethod
		{
			None = -1,
			Certificate = 0,
			Passport = 1
		}

		#region Constructor

		public MainWindowViewModel(ICertificateDataProvider certificateAuthorizationViewModel, 
			IPassportDataProvider passportAuthorizationViewModel,
			IDateTimeProvider currentDateTimeViewModel, 
			IVote voter,
			IList<Candidate> candidateList,
			IConfirmationIdCreator confirmationIdCreator)
		{
			_voter = voter;
			_confirmationIdCreator = confirmationIdCreator;
			_authorizationMethods =
				new ReadOnlyCollection<string>(CreateAuthonticationMethodsCommands());
			CertificateAuthorization = certificateAuthorizationViewModel;
			PassportAuthorization = passportAuthorizationViewModel;
			CurrentDateTime = currentDateTimeViewModel;
			_candidateList = candidateList;
			CandidateNameList = new ReadOnlyCollection<string>(_candidateList.Select(c => c.Fio).ToList());
			SelectedCandidateIndex = -1;
			VoteCommand = new CommandViewModel(Resources.MainWindowViewModel_Command_Vote, 
				CreateVoteCommand());
			SelectedAuthorizationMethod = (int)AuthorizationMethod.Certificate;
		}

		#endregion

		#region Public properties

		public ReadOnlyCollection<string> AuthorizationMethods
		{
			get { return _authorizationMethods; }
		}

		private int _selectedAuthorizationMethod;
		public int SelectedAuthorizationMethod
		{
			get { return _selectedAuthorizationMethod; }
			set
			{
				_selectedAuthorizationMethod = value;
				OnPropertyChanged("SelectedAuthorizationMethod");
			}
		}

		public ICertificateDataProvider CertificateAuthorization { get; private set; }

		public IPassportDataProvider PassportAuthorization { get; private set; }

		public IDateTimeProvider CurrentDateTime { get; private set; }

		public ReadOnlyCollection<string> CandidateNameList { get; private set; }

		public int SelectedCandidateIndex { get; set; }

		public CommandViewModel VoteCommand { get; private set; }

		#endregion

		#region Private data

		private readonly IVote _voter;
	    private readonly IConfirmationIdCreator _confirmationIdCreator;
		private readonly IList<Candidate> _candidateList;
		private readonly ReadOnlyCollection<string> _authorizationMethods;

		#endregion

		#region Private methods

		private static List<string> CreateAuthonticationMethodsCommands()
		{
			return new List<string>
			       	{
			       		Resources.MainWindowViewModel_Command_AuthorizationWithCertificate, 
			       		Resources.MainWindowViewModel_Command_AuthorizationWithPassport,
			       	};
		}

		private RelayCommand CreateVoteCommand()
		{
			return new RelayCommand(o => Vote(), o => CanVote());
		}

		private bool CanVote()
		{
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.None || SelectedCandidateIndex == -1)
			{
				return false;
			}
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Certificate)
			{
				return CertificateAuthorization.IsDataReady();
			}
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Passport)
			{
				return PassportAuthorization.IsDataReady();
			}
			throw new Exception("Unexpected runtime error. Wrong authorization state");
		}

		private void Vote()
		{
			var now = CurrentDateTime.Now;
			var candidate = _candidateList[SelectedCandidateIndex];
			var voterUniqueId = GetVoterUniqueId();
			var confirmationMessage = CreateConfirmationMessage(voterUniqueId, now, candidate);
			var messageBoxResult = MessageBox.Show(confirmationMessage, "Внимание!", MessageBoxButton.OKCancel);
			if (messageBoxResult == MessageBoxResult.Cancel)
			{
				return;
			}
			var confirmationId = _confirmationIdCreator.Create(voterUniqueId, candidate.Id, now);
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Certificate)
			{
				_voter.Vote(_candidateList[SelectedCandidateIndex], CertificateAuthorization.Certificate, confirmationId);
			}
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Passport)
			{
				_voter.Vote(_candidateList[SelectedCandidateIndex], PassportAuthorization.VoterPassportNumber, PassportAuthorization.VoterPassword, confirmationId);
			}
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.None)
			{
				throw new InvalidOperationException("Authorization method not selected");
			}
			var clipboardError = false;
			try
			{
				Clipboard.SetText(confirmationId);
			}
			catch (COMException)
			{
				clipboardError = true;
			}
			MessageBox.Show(string.Format("Ваш голос принят. Ваш проверочный идентификатор{0} скопирован в буфер обмена : {1}", 
				clipboardError ? " не" :  "", confirmationId));
		}

		private string GetVoterUniqueId()
		{
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Certificate)
			{
				return CertificateAuthorization.Certificate.Thumbprint;
			}
			if (SelectedAuthorizationMethod == (int)AuthorizationMethod.Passport)
			{
				return PassportAuthorization.VoterPassportNumber;
			}
			throw new InvalidOperationException("Invalid authorization method");
		}

		private static string CreateConfirmationMessage(string voterUniqueId, DateTime now, Candidate candidate)
		{
			var builder = new StringBuilder();
			builder.AppendFormat("Проверьте введённые данные. Ваш уникальный идентификатор: {0}. Время голосования : {1}. Выбранный кандидат: ФИО - {2}, уникальный идентификатор - {3}.",
				voterUniqueId, now, candidate.Fio, candidate.Id);
			return builder.ToString();
		}

		#endregion
	}
}
